﻿using System.Collections;
using System.Threading;
using System.CodeDom;
using System;

namespace OrganizationName.Factory
{
    public class RuntimeContext
    {
        private const string _THREAD_DATA_KEY = "3399E423-2CAD-46F3-A5E2-418E81B14C04";

        private Hashtable _Storage = new Hashtable();
        
        [ThreadStatic]
        private static RuntimeContext _Current;

        public static RuntimeContext Current
        {
            get
            {
                if (_Current == null)
                {
                    lock (typeof(RuntimeContext))
                    {
                        if (_Current == null)
                        {
                            _Current = new RuntimeContext();
                        }
                    }
                }
                return _Current;
            }
        }

        internal void Update(Hashtable runtimeContextStorage)
        {
            if (runtimeContextStorage == null)
            {
                throw new ArgumentNullException();
            }
            _Storage = runtimeContextStorage;
        }

        public object this[string name]
        {
            get
            {
                return _Storage[name];
            }
            set
            {
                _Storage[name] = value;
            }
        }

        internal static CodeExpression CompileTimeGet(string contextVariableName, System.Type targetType)
        {
            return new CodeCastExpression
            (
                targetType,
                CompileTimeGet(contextVariableName)
            );
        }

        internal static CodeExpression CompileTimeGet(string contextVariableName)
        {
            return new CodeIndexerExpression
            (
                new CodePropertyReferenceExpression
                (
                    new CodeTypeReferenceExpression(typeof(RuntimeContext)),
                    "Current"
                ),
                new CodePrimitiveExpression(contextVariableName)
            );
        }

        internal static CodeAssignStatement CompileTimeSet(string contextVariableName, CodeExpression valueExpression)
        {
            return new CodeAssignStatement
            (
                CompileTimeGet(contextVariableName),
                valueExpression
            );
        }
    }
}
